package com.me.study.concurrent.threadPool;

import com.me.common.util.SleepUtil;
import jodd.util.concurrent.ThreadFactoryBuilder;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * TODO 局部变量里定义的线程池不会主动回收，存在线程泄露问题！！！！！<p></p>
 *
 * 线程池中子线程异常测试类：子线程报错后，主线程是否继续<p>
 *     依赖获取结果的顺序，即：第一个线程执行时间很长且成功了，及时其他线程快速异常也来不及中断了！！！
 *
 * @author ME
 * @date   2019/6/3
 */
public class TestPoolException {

    public static void main(String[] args) {
        ThreadFactory customizedFactory = new NamedThreadFactory("customized-pool");// customized-pool3-thread-6
        ThreadFactory lang3Factory = new BasicThreadFactory.Builder().namingPattern("lang3-pool-thread-%d").build();// lang3-pool-thread-8
        ThreadFactory springFactory = new CustomizableThreadFactory("spring-pool-");// spring-pool-9
        // Google guava 工具类 提供的
        ThreadFactory guavaFactory = new ThreadFactoryBuilder().setNameFormat("guavaThread-pool-").get();
        // java开源工具包-Jodd框架 内
        ThreadFactory joddFactory = new jodd.util.concurrent.ThreadFactoryBuilder().setNameFormat("joddThread-pool-").get();

        ExecutorService cachedThreadPool = new ThreadPoolExecutor(5, 5,
                5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10), lang3Factory);
        List<MyThead> tasks = new ArrayList<>();

        // 异常线程
        MyThead exceptionThead = new MyThead("MyThread-Exception", true);
        tasks.add(exceptionThead);
        for (int i = 1; i < 5; i++) {
            MyThead myThead = new MyThead("MyThread-" + i, false);
            tasks.add(myThead);
        }

        try {
            // TODO 通过 invokeAll() 批量提交任务，会阻塞主线程
            List<Future<String>> futures = cachedThreadPool.invokeAll(tasks);

            // 获得返回结果，再次阻塞主线程
            // for (Future<String> future : futures) {
            //     try {
            //         String result = future.get();
            //         System.out.println(result);
            //     } catch (ExecutionException e) {
            //         System.out.println("===============线程池中的线程出错了！！！");
            //         e.printStackTrace();
            //         System.out.println("===============优雅的关闭线程池");
            //         cachedThreadPool.shutdownNow();
            //     }
            // }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        int i = 1;
        while (true) {
            SleepUtil.seconds(1);
            System.out.println(i++);
        }
    }

    public static class MyThead implements Callable<String> {
        private String name;
        private boolean exceptionFlag;

        public MyThead(String name, boolean exceptionFlag) {
            this.name = name;
            this.exceptionFlag = exceptionFlag;
        }

        @Override
        public String call() throws Exception {
            Thread.currentThread().setName(name);
            if (exceptionFlag) {
                SleepUtil.seconds(3);
            } else {
                SleepUtil.seconds(6);
            }
            if (exceptionFlag) {
                System.out.println(String.format("[%s] %s", name, "随机出现的异常"));
                throw new RuntimeException("随机出现的异常");
            }

            System.out.println(String.format("[%s] %s", name, ": success"));
            return String.format("[%s] %s", name, ": success");
        }
    }
}
